home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fslcl / fslclDomain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  20.5 KB  |  628 lines

  1. /* 
  2.  * fslclDomain.c --
  3.  *
  4.  *    Implementation of name-space operations in the local domain.
  5.  *    The routines here are called via the prefix table.
  6.  *    They use FslclLookup (in fsLocalLookup.c) to do the guts of
  7.  *    recursive name lookup.
  8.  *
  9.  * Copyright (C) 1987 Regents of the University of California
  10.  * All rights reserved.
  11.  * Permission to use, copy, modify, and distribute this
  12.  * software and its documentation for any purpose and without
  13.  * fee is hereby granted, provided that the above copyright
  14.  * notice appear in all copies.  The University of California
  15.  * makes no representations about the suitability of this
  16.  * software for any purpose.  It is provided "as is" without
  17.  * express or implied warranty.
  18.  */
  19.  
  20. #ifndef lint
  21. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fslcl/fslclDomain.c,v 9.12 91/09/10 18:38:43 rab Exp $ SPRITE (Berkeley)";
  22. #endif not lint
  23.  
  24.  
  25. #include <sprite.h>
  26. #include <fs.h>
  27. #include <fsconsist.h>
  28. #include <fsio.h>
  29. #include <fsutil.h>
  30. #include <fsNameOps.h>
  31. #include <fsprefix.h>
  32. #include <fslclInt.h>
  33. #include <fsdm.h>
  34. #include <rpc.h>
  35. #include <vm.h>
  36. #include <string.h>
  37. #include <proc.h>
  38. #include <spriteTime.h>
  39.  
  40. char *fslclEmptyDirBlock;
  41.  
  42. /*
  43.  *----------------------------------------------------------------------
  44.  *
  45.  * Fslcl_DomainInit --
  46.  *
  47.  *    Do general initialization for the local domain.
  48.  *
  49.  * Results:
  50.  *    None.
  51.  *
  52.  * Side effects:
  53.  *    Initializes the domain table and the image of a new directory.
  54.  *    
  55.  *
  56.  *----------------------------------------------------------------------
  57.  */
  58. void
  59. Fslcl_DomainInit()
  60. {
  61.     register Fslcl_DirEntry *dirEntryPtr;
  62.  
  63.     Fsdm_Init();
  64.  
  65.     fslclEmptyDirBlock = (char *)malloc(FSLCL_DIR_BLOCK_SIZE);
  66.     dirEntryPtr = (Fslcl_DirEntry *)fslclEmptyDirBlock;
  67.     dirEntryPtr->fileNumber = FSDM_ROOT_FILE_NUMBER;
  68.     dirEntryPtr->nameLength = strlen(".");
  69.     dirEntryPtr->recordLength = Fslcl_DirRecLength(dirEntryPtr->nameLength);
  70.     (void)strcpy(dirEntryPtr->fileName, ".");
  71.     dirEntryPtr = (Fslcl_DirEntry *)((int)dirEntryPtr + dirEntryPtr->recordLength);
  72.     dirEntryPtr->fileNumber = FSDM_ROOT_FILE_NUMBER;
  73.     dirEntryPtr->nameLength = strlen("..");
  74.     dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - Fslcl_DirRecLength(1);
  75.     (void)strcpy(dirEntryPtr->fileName, "..");
  76. }
  77.  
  78. /*
  79.  *----------------------------------------------------------------------
  80.  *
  81.  * FslclExport --
  82.  *
  83.  *    This is called from the RPC_FS_PREFIX stub to export a domain
  84.  *    to a remote Sprite host.  The prefix table has already been
  85.  *    examined, and we are passed in the handle that's hooked to it.
  86.  *    This uses Fsio_FileNameOpen to setup Fsio_FileState so the client
  87.  *    can set up a remote file handle for its own prefix table.
  88.  *
  89.  * Results:
  90.  *    That of Fsio_FileNameOpen
  91.  *
  92.  * Side effects:
  93.  *    Adds the client to the set of clients using the directory that
  94.  *    is the top of the local domain.
  95.  *    
  96.  *
  97.  *----------------------------------------------------------------------
  98.  */
  99. ReturnStatus
  100. FslclExport(hdrPtr, clientID, ioFileIDPtr, dataSizePtr, clientDataPtr)
  101.      Fs_HandleHeader    *hdrPtr;    /* A handle from the prefix table. */
  102.      int        clientID;    /* Host ID of client importing prefix */
  103.      register Fs_FileID    *ioFileIDPtr;    /* Return - I/O handle ID */
  104.      int        *dataSizePtr;    /* Return - sizeof(Fsio_FileState) */
  105.      ClientData        *clientDataPtr;    /* Return - ref to Fsio_FileState */
  106. {
  107.     register Fsio_FileIOHandle *handlePtr = (Fsio_FileIOHandle *)hdrPtr;
  108.     register ReturnStatus status;
  109.     Fs_OpenArgs openArgs;
  110.     Fs_OpenResults openResults;
  111.  
  112.     bzero((Address)&openArgs, sizeof(openArgs));
  113.     openArgs.clientID = clientID;
  114.     openArgs.useFlags = FS_PREFIX;
  115.  
  116.     Fsutil_HandleLock(handlePtr);
  117.     status = Fsio_FileNameOpen(handlePtr, &openArgs, &openResults);
  118.     if (status == SUCCESS) {
  119.     *ioFileIDPtr = openResults.ioFileID;
  120.     *dataSizePtr = openResults.dataSize;
  121.     *clientDataPtr = openResults.streamData;
  122.     }
  123.     return(status);
  124. }
  125.  
  126. /*
  127.  *----------------------------------------------------------------------
  128.  *
  129.  * FslclOpen --
  130.  *
  131.  *      Open a file stored locally.  This uses FslclLookup to get a
  132.  *    regular handle on the file, and then calls the server-open
  133.  *    routine to bundle up state needed later by the client-open routine.
  134.  *    That routine will set up a handle for I/O, which for devices and
  135.  *    other things will be different than the regular handle.
  136.  *
  137.  * Results:
  138.  *    An error code.  The results include a pointer to some client data
  139.  *    packaged up by the server-open routine.
  140.  *
  141.  * Side effects:
  142.  *    The file-type server-open routine is called to package
  143.  *    up state for the client-open routine.
  144.  *
  145.  *----------------------------------------------------------------------
  146.  */
  147. ReturnStatus
  148. FslclOpen(prefixHandlePtr, relativeName, argsPtr, resultsPtr, 
  149.         newNameInfoPtrPtr)
  150.     Fs_HandleHeader    *prefixHandlePtr; /* Handle that indicates the starting 
  151.                        * point of the lookup */
  152.     char     *relativeName;          /* The name of the file to open */
  153.     Address     argsPtr;          /* Bundled arguments for us */
  154.     Address     resultsPtr;          /* Bundled results for us */
  155.     Fs_RedirectInfo **newNameInfoPtrPtr;   /* We return this if the server 
  156.                        * leaves its domain during the 
  157.                        * lookup. */
  158. {
  159.     register Fs_OpenArgs *openArgsPtr = (Fs_OpenArgs *)argsPtr;
  160.     register Fs_OpenResults *openResultsPtr = (Fs_OpenResults *)resultsPtr;
  161.     Fsio_FileIOHandle *handlePtr;    /* The handle returned for the file */
  162.     ReturnStatus     status;        /* Error return from RPC */
  163.  
  164.     status = FslclLookup(prefixHandlePtr, relativeName, &openArgsPtr->rootID,
  165.         openArgsPtr->useFlags, openArgsPtr->type, openArgsPtr->clientID,
  166.         &openArgsPtr->id, openArgsPtr->permissions, 0, &handlePtr,
  167.         newNameInfoPtrPtr);
  168.     if (status == SUCCESS) {
  169.     /*
  170.      * Call the file-type server-open routine to set up any state
  171.      * needed later by the client to open a stream to the file.
  172.      * For regular files, this is when cache consistency is done.
  173.      */
  174.     status = (*fsio_OpenOpTable[handlePtr->descPtr->fileType].nameOpen)
  175.         (handlePtr, openArgsPtr, openResultsPtr);
  176.     openResultsPtr->nameID = handlePtr->hdr.fileID;
  177.     if (openArgsPtr->clientID != rpc_SpriteID) {
  178.         openResultsPtr->nameID.type = FSIO_RMT_FILE_STREAM;
  179.     }
  180.     Fsutil_HandleRelease(handlePtr, FALSE);
  181.     Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
  182.     }
  183.     return(status);
  184. }
  185.  
  186. /*
  187.  *----------------------------------------------------------------------
  188.  *
  189.  * FslclGetAttrPath --
  190.  *
  191.  *    Get the attributes of a local file given its path name.  The attributes
  192.  *    are copied from the disk descriptor need to be updated by contacting
  193.  *    the I/O server for the file (for non-regular files).
  194.  *
  195.  * Results:
  196.  *    Return code from FslclLookup.
  197.  *
  198.  * Side effects:
  199.  *    Does call-backs to clients to grab up-to-date access and modify
  200.  *    times for regular files.
  201.  *
  202.  *----------------------------------------------------------------------
  203.  */
  204. ReturnStatus
  205. FslclGetAttrPath(prefixHandlePtr, relativeName, argsPtr, resultsPtr,
  206.                   newNameInfoPtrPtr)
  207.     Fs_HandleHeader    *prefixHandlePtr;    /* Handle from prefix table */
  208.     char        *relativeName;        /* The name of the file. */
  209.     Address        argsPtr;        /* Bundled arguments for us */
  210.     Address        resultsPtr;        /* == NIL */
  211.     Fs_RedirectInfo    **newNameInfoPtrPtr;    /* We return this if the server
  212.                          * leaves its domain during
  213.                          * the lookup. */
  214. {
  215.     ReturnStatus    status;
  216.     Boolean        isExeced;
  217.     Fs_OpenArgs         *openArgsPtr;
  218.     Fsio_FileIOHandle *handlePtr;
  219.     Fs_GetAttrResults    *attrResultsPtr;
  220.     Fs_OpenResults    openResults;
  221.  
  222.  
  223.     openArgsPtr =  (Fs_OpenArgs *)argsPtr;
  224.     attrResultsPtr = (Fs_GetAttrResults *)resultsPtr;
  225.  
  226.     status = FslclLookup(prefixHandlePtr, relativeName, &openArgsPtr->rootID,
  227.             openArgsPtr->useFlags, openArgsPtr->type,
  228.             openArgsPtr->clientID,
  229.             &openArgsPtr->id, openArgsPtr->permissions, 0,
  230.             &handlePtr, newNameInfoPtrPtr);
  231.     if (status != SUCCESS) {
  232.     return(status);
  233.     }
  234.     /*
  235.      * Do call-backs to get attributes cached (for regular files) on clients,
  236.      * then copy the attributes from the disk descriptor.
  237.      */
  238.     Fsconsist_GetClientAttrs(handlePtr, openArgsPtr->clientID, &isExeced);
  239.     FslclAssignAttrs(handlePtr, isExeced, attrResultsPtr->attrPtr);
  240.     /*
  241.      * Get the I/O fileID so our client can contact the I/O server.
  242.      */
  243.     openArgsPtr->useFlags = 0;
  244.     status = (*fsio_OpenOpTable[handlePtr->descPtr->fileType].nameOpen)
  245.         (handlePtr, openArgsPtr, &openResults);
  246.     *attrResultsPtr->fileIDPtr = openResults.ioFileID;
  247.  
  248.     if (status != SUCCESS) {
  249.     printf("FslclGetAttrPath, nameOpen of \"%s\" <%d,%d> failed <%x>\n",
  250.         relativeName, handlePtr->hdr.fileID.minor,
  251.         handlePtr->hdr.fileID.major, status);
  252.     }
  253.     Fsutil_HandleRelease(handlePtr, FALSE);
  254.     Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
  255.     return(status);
  256. }
  257.  
  258. /*
  259.  *----------------------------------------------------------------------
  260.  *
  261.  * FslclSetAttrPath --
  262.  *
  263.  *    Set the attributes of a local file given its pathname.  First
  264.  *    we update the disk descriptor, then call the nameOpen routine
  265.  *    to get an I/O handle for the file.  This is used by our caller
  266.  *    to branch to the stream-type setIOAttr routine.
  267.  *
  268.  * Results:
  269.  *    None.
  270.  *
  271.  * Side effects:
  272.  *    None.
  273.  *
  274.  *----------------------------------------------------------------------
  275.  */
  276. ReturnStatus
  277. FslclSetAttrPath(prefixHandlePtr, relativeName, argsPtr, resultsPtr,
  278.                   newNameInfoPtrPtr)
  279.     Fs_HandleHeader *prefixHandlePtr;    /* File handle from prefix table */
  280.     char *relativeName;        /* The name of the file. */
  281.     Address argsPtr;        /* Bundled arguments for us */
  282.     Address resultsPtr;        /* Bundled results from us */
  283.     Fs_RedirectInfo **newNameInfoPtrPtr;/*We return this if the server leaves its
  284.                         * domain during the lookup. */
  285. {
  286.     ReturnStatus        status;
  287.     Fs_SetAttrArgs        *setAttrArgsPtr;
  288.     Fs_OpenArgs            *openArgsPtr;
  289.     Fs_FileID            *fileIDPtr;
  290.     Fsio_FileIOHandle        *handlePtr;
  291.     Fs_OpenResults        openResults;
  292.  
  293.     setAttrArgsPtr =  (Fs_SetAttrArgs *)argsPtr;
  294.     openArgsPtr = &setAttrArgsPtr->openArgs;
  295.     fileIDPtr = (Fs_FileID *)resultsPtr;
  296.  
  297.     status = FslclLookup(prefixHandlePtr, relativeName, &openArgsPtr->rootID,
  298.             openArgsPtr->useFlags, openArgsPtr->type,
  299.             openArgsPtr->clientID,
  300.             &openArgsPtr->id, openArgsPtr->permissions, 0,
  301.             &handlePtr, newNameInfoPtrPtr);
  302.     if (status != SUCCESS) {
  303.     return(status);
  304.     }
  305.     /*
  306.      * Set the attributes on the disk descriptor.
  307.      */
  308.     Fsutil_HandleUnlock(handlePtr);
  309.     status = FslclSetAttr(&handlePtr->hdr.fileID, &setAttrArgsPtr->attr,
  310.                 &openArgsPtr->id, setAttrArgsPtr->flags);
  311.     /*
  312.      * Get the I/O handle so our client can contact the I/O server.
  313.      */
  314.     if (status == SUCCESS) {
  315.     Fsutil_HandleLock(handlePtr);
  316.     openArgsPtr->useFlags = 0;
  317.     status = (*fsio_OpenOpTable[handlePtr->descPtr->fileType].nameOpen)
  318.         (handlePtr, openArgsPtr, &openResults);
  319.     *fileIDPtr = openResults.ioFileID;
  320.  
  321.     if (status != SUCCESS) {
  322.         printf(
  323.         "FslclSetAttrPath, nameOpen of \"%s\" <%d,%d> failed <%x>\n",
  324.         relativeName, handlePtr->hdr.fileID.minor,
  325.         handlePtr->hdr.fileID.major, status);
  326.     }
  327.     }
  328.     Fsutil_HandleRelease(handlePtr, FALSE);
  329.     Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
  330.     return(status);
  331. }
  332.  
  333. /*
  334.  *----------------------------------------------------------------------
  335.  *
  336.  * FslclMakeDevice --
  337.  *
  338.  *    Create a device file.  A file is created with type FS_DEVICE and
  339.  *    then the handle and the descriptor have their device information
  340.  *    updated from the MakeDevice parameters.  This device information,
  341.  *    along with the FS_DEVICE file type, causes I/O operations on the
  342.  *    file to be directed to the device driver routines.
  343.  *
  344.  * Results:
  345.  *    The results of the lookup if it fails, or SUCCESS.
  346.  *
  347.  * Side effects:
  348.  *    Create the file and set up the descriptor's and handle' device info.
  349.  *
  350.  *----------------------------------------------------------------------
  351.  */
  352. /*ARGSUSED*/
  353. ReturnStatus
  354. FslclMakeDevice(prefixHandle, relativeName, argsPtr, resultsPtr,
  355.                 newNameInfoPtrPtr)
  356.     Fs_HandleHeader    *prefixHandle;    /* Reference to prefix of the domain */
  357.     char        *relativeName;    /* The name of the file. */
  358.     Address        argsPtr;    /* Bundled arguments for us */
  359.     Address        resultsPtr;    /* == NIL */
  360.     Fs_RedirectInfo    **newNameInfoPtrPtr;    /* We return this if the server
  361.                      *leaves its domain during lookup. */
  362. {
  363.     ReturnStatus    status;
  364.     Fs_MakeDeviceArgs    *makeDevArgsPtr;
  365.     Fsio_FileIOHandle *handlePtr;
  366.     register Fsdm_FileDescriptor *descPtr;
  367.  
  368.     makeDevArgsPtr = (Fs_MakeDeviceArgs *)argsPtr;
  369.     status = FslclLookup(prefixHandle, relativeName,
  370.         &makeDevArgsPtr->open.rootID,
  371.         FS_CREATE | FS_EXCLUSIVE | FS_FOLLOW, FS_DEVICE,
  372.         makeDevArgsPtr->open.clientID,
  373.         &makeDevArgsPtr->open.id, makeDevArgsPtr->open.permissions,
  374.         0, &handlePtr, newNameInfoPtrPtr);
  375.     if (status == SUCCESS) {
  376.     descPtr = handlePtr->descPtr;
  377.     descPtr->devServerID = makeDevArgsPtr->device.serverID;
  378.     descPtr->devType = makeDevArgsPtr->device.type;
  379.     descPtr->devUnit = makeDevArgsPtr->device.unit;
  380.     descPtr->flags |= FSDM_FD_OTHERS_DIRTY;
  381.     status = Fsdm_FileDescStore(handlePtr, FALSE);
  382.     Fsutil_HandleRelease(handlePtr, TRUE);
  383.     }
  384.     return(status);
  385. }
  386.  
  387.  
  388. /*
  389.  *----------------------------------------------------------------------
  390.  *
  391.  * FslclMakeDir --
  392.  *
  393.  *    Make the named directory.
  394.  *
  395.  * Results:
  396.  *    An error code.
  397.  *
  398.  * Side effects:
  399.  *    None.
  400.  *
  401.  *----------------------------------------------------------------------
  402.  */
  403. /*ARGSUSED*/
  404. ReturnStatus
  405. FslclMakeDir(prefixHandle, relativeName, argsPtr, resultsPtr, 
  406.            newNameInfoPtrPtr)
  407.     Fs_HandleHeader    *prefixHandle;    /* Reference to prefix of the domain */
  408.     char        *relativeName;    /* The name of the dir. to create */
  409.     Address        argsPtr;    /* Ref. to Fs_OpenArgs */
  410.     Address        resultsPtr;    /* == NIL */
  411.     Fs_RedirectInfo    **newNameInfoPtrPtr;    /* We return this if the server
  412.                      * leaves its domain during lookup. */
  413. {
  414.     ReturnStatus    status;
  415.     Fs_OpenArgs        *openArgsPtr;    /* Pointer to bundled arguments */
  416.     Fsio_FileIOHandle    *handlePtr;
  417.  
  418.     openArgsPtr = (Fs_OpenArgs *)argsPtr;
  419.     status = FslclLookup(prefixHandle, relativeName, &openArgsPtr->rootID,
  420.         openArgsPtr->useFlags, openArgsPtr->type, openArgsPtr->clientID,
  421.         &openArgsPtr->id, openArgsPtr->permissions, 0, &handlePtr,
  422.         newNameInfoPtrPtr);
  423.     if (status == SUCCESS) {
  424.     Fsutil_HandleRelease(handlePtr, TRUE);
  425.     Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
  426.     }
  427.     return(status);
  428. }
  429.  
  430.  
  431. /*
  432.  *----------------------------------------------------------------------
  433.  *
  434.  * FslclRemove --
  435.  *
  436.  *    Remove a file from the local domain.
  437.  *
  438.  * Results:
  439.  *    An error code.
  440.  *
  441.  * Side effects:
  442.  *    None.
  443.  *
  444.  *----------------------------------------------------------------------
  445.  */
  446. /*ARGSUSED*/
  447. ReturnStatus
  448. FslclRemove(prefixHandle, relativeName, argsPtr, resultsPtr, 
  449.           newNameInfoPtrPtr)
  450.     Fs_HandleHeader    *prefixHandle;    /* Reference to prefix of the domain */
  451.     char        *relativeName;    /* The name of the file to remove */
  452.     Address        argsPtr;    /* Bundled arguments for us */
  453.     Address        resultsPtr;    /* == NIL */
  454.     Fs_RedirectInfo    **newNameInfoPtrPtr;    /* We return this if the server 
  455.                      * leaves its domain during lookup. */
  456. {
  457.     register ReturnStatus status;
  458.     register Fs_LookupArgs *lookupArgsPtr;
  459.  
  460.     lookupArgsPtr = (Fs_LookupArgs *)argsPtr;
  461.     status = FslclLookup(prefixHandle, relativeName, &lookupArgsPtr->rootID,
  462.         lookupArgsPtr->useFlags, FS_FILE, lookupArgsPtr->clientID,
  463.         &lookupArgsPtr->id, 0, 0, (Fsio_FileIOHandle **)NIL,
  464.         newNameInfoPtrPtr);
  465.     return(status);
  466. }
  467.  
  468. /*
  469.  *----------------------------------------------------------------------
  470.  *
  471.  * FslclRemoveDir --
  472.  *
  473.  *    Remove a directory from the local domain.
  474.  *
  475.  * Results:
  476.  *    An error code.
  477.  *
  478.  * Side effects:
  479.  *    None.
  480.  *
  481.  *----------------------------------------------------------------------
  482.  */
  483. /*ARGSUSED*/
  484. ReturnStatus
  485. FslclRemoveDir(prefixHandle, relativeName, argsPtr, resultsPtr, 
  486.           newNameInfoPtrPtr)
  487.     Fs_HandleHeader    *prefixHandle;    /* Reference to prefix of the domain */
  488.     char        *relativeName;    /* The name of the file to remove */
  489.     Address        argsPtr;    /* Bundled arguments for us */
  490.     Address        resultsPtr;    /* == NIL */
  491.     Fs_RedirectInfo    **newNameInfoPtrPtr;    /* We return this if the server 
  492.                      * leaves its domain during lookup. */
  493. {
  494.     register ReturnStatus status;
  495.     register Fs_LookupArgs *lookupArgsPtr;
  496.  
  497.     lookupArgsPtr = (Fs_LookupArgs *)argsPtr;
  498.     status = FslclLookup(prefixHandle, relativeName, &lookupArgsPtr->rootID,
  499.         lookupArgsPtr->useFlags, FS_DIRECTORY, lookupArgsPtr->clientID,
  500.         &lookupArgsPtr->id, 0, 0, (Fsio_FileIOHandle **)NIL,
  501.         newNameInfoPtrPtr);
  502.     return(status);
  503. }
  504.  
  505. /*
  506.  *----------------------------------------------------------------------
  507.  *
  508.  * FslclRename --
  509.  *
  510.  *    Rename a local file.
  511.  *
  512.  * Results:
  513.  *    An error code.
  514.  *
  515.  * Side effects:
  516.  *    None.
  517.  *
  518.  *----------------------------------------------------------------------
  519.  */
  520. ReturnStatus
  521. FslclRename(prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  522.         lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  523.     Fs_HandleHeader    *prefixHandle1;    /* Token from the prefix table */
  524.     char        *relativeName1;    /* The new name of the file. */
  525.     Fs_HandleHeader    *prefixHandle2;    /* Token from the prefix table */
  526.     char        *relativeName2;    /* The new name of the file. */
  527.     Fs_LookupArgs    *lookupArgsPtr;    /* Contains ID info */
  528.     Fs_RedirectInfo    **newNameInfoPtrPtr;    /* We return this if the server
  529.                          * leaves its domain during
  530.                          * lookup. */
  531.     Boolean        *name1ErrorPtr;    /* TRUE if redirect info or stale
  532.                      * handle error is for the first name,
  533.                      * FALSE if for the second. */
  534. {
  535.     ReturnStatus status;
  536.  
  537.     lookupArgsPtr->useFlags = FS_LINK | FS_RENAME;
  538.     status = FslclHardLink(prefixHandle1, relativeName1, prefixHandle2,
  539.         relativeName2, lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr);
  540.     if (status == SUCCESS) {
  541.     lookupArgsPtr->useFlags = FS_DELETE | FS_RENAME;
  542.     status = FslclRemove(prefixHandle1, relativeName1, 
  543.             (Address) lookupArgsPtr, (Address)NIL, newNameInfoPtrPtr);
  544.     }
  545.     return(status);
  546. }
  547.  
  548. /*
  549.  *----------------------------------------------------------------------
  550.  *
  551.  * FslclHardLink --
  552.  *
  553.  *    Make another name for an existing file.
  554.  *
  555.  * Results:
  556.  *    An error code.
  557.  *
  558.  * Side effects:
  559.  *    None.
  560.  *
  561.  *----------------------------------------------------------------------
  562.  */
  563. ReturnStatus
  564. FslclHardLink(prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  565.         lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  566.     Fs_HandleHeader    *prefixHandle1;    /* Token from the prefix table */
  567.     char        *relativeName1;    /* The new name of the file. */
  568.     Fs_HandleHeader    *prefixHandle2;    /* Token from the prefix table */
  569.     char        *relativeName2;    /* The new name of the file. */
  570.     Fs_LookupArgs    *lookupArgsPtr;    /* Contains ID info */
  571.     Fs_RedirectInfo    **newNameInfoPtrPtr;    /* We return this if the server
  572.                          * leaves its domain during
  573.                          * lookup. */
  574.     Boolean        *name1ErrorPtr;    /* TRUE if redirect-info or stale
  575.                      * handle error is for first pathname,
  576.                      * FALSE if for the second. */
  577. {
  578.     ReturnStatus status;
  579.     Fsio_FileIOHandle *handle1Ptr;
  580.     Fsio_FileIOHandle *handle2Ptr;
  581.  
  582.     *name1ErrorPtr = FALSE;
  583.  
  584.     /*
  585.      * This lookup gets a locked handle on the (presumably) existing file.
  586.      */
  587.     status = FslclLookup(prefixHandle1, relativeName1, &lookupArgsPtr->rootID,
  588.        lookupArgsPtr->useFlags & FS_FOLLOW, FS_FILE,
  589.        lookupArgsPtr->clientID, &lookupArgsPtr->id,
  590.        0, 0, (Fsio_FileIOHandle **)&handle1Ptr, newNameInfoPtrPtr);
  591.     if (status != SUCCESS) {
  592.     *name1ErrorPtr = TRUE;
  593.     return(status);
  594.     }
  595.     Fsutil_HandleUnlock(handle1Ptr);
  596.     if (prefixHandle2 == (Fs_HandleHeader *)NIL ||
  597.     prefixHandle2->fileID.major != prefixHandle1->fileID.major) {
  598.     /*
  599.      * The second pathname which isn't in our domain.  We have
  600.      * been called in this case to see if the first pathname would
  601.      * redirect away from us, but it didn't.
  602.      */
  603.     status = FS_CROSS_DOMAIN_OPERATION;
  604.     } else {
  605.     /*
  606.      * This lookup does the linking.  If our caller has set FS_RENAME in
  607.      * lookupArgsPtr->useFlags then directories can be linked.  Handle1
  608.      * is unlocked because the linking will end up locking it again.
  609.      * The result of a successful return from this call is that
  610.      * both handle1 and handle2 reference the same handle, and that
  611.      * handle is locked.
  612.      */
  613.     status = FslclLookup(prefixHandle2, relativeName2,
  614.         &lookupArgsPtr->rootID,
  615.         lookupArgsPtr->useFlags, handle1Ptr->descPtr->fileType,
  616.         lookupArgsPtr->clientID,
  617.         &lookupArgsPtr->id, 0, handle1Ptr->hdr.fileID.minor,
  618.         (Fsio_FileIOHandle **)&handle2Ptr, newNameInfoPtrPtr);
  619.     }
  620.     if (status == SUCCESS) {
  621.     Fsutil_HandleRelease(handle2Ptr, TRUE);
  622.     Fsdm_DomainRelease(handle2Ptr->hdr.fileID.major);
  623.     }
  624.     Fsutil_HandleRelease(handle1Ptr, FALSE);
  625.     Fsdm_DomainRelease(handle1Ptr->hdr.fileID.major);
  626.     return(status);
  627. }
  628.